package org.xxpay.manage.sys.ctrl;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xxpay.core.common.annotation.MethodLog;
import org.xxpay.core.common.constant.Constant;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.domain.BizResponse;
import org.xxpay.core.common.domain.XxPayResponse;
import org.xxpay.core.common.util.BtUtil;
import org.xxpay.core.common.util.MD5Util;
import org.xxpay.core.common.util.StrUtil;
import org.xxpay.core.common.vo.DBApplicationConfig;
import org.xxpay.manage.common.ctrl.BaseController;
import org.xxpay.manage.common.service.RpcCommonService;
import org.xxpay.manage.mq.topic.MqTopic4ModifySysConfig;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.util.*;

@Controller
@RequestMapping(Constant.MGR_CONTROLLER_ROOT_PATH + "/sys/config")
public class SysConfigController extends BaseController {

    @Autowired private StringRedisTemplate stringRedisTemplate;

    @Autowired private MqTopic4ModifySysConfig mqTopic4ModifySysConfig;

    /**
     * 查询配置信息
     * @return
     */
    @RequestMapping("/getAll")
    @ResponseBody
    public ResponseEntity<?> getAll(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        JSONObject obj = commonService.sysConfigService.getSysConfig();
        return ResponseEntity.ok(XxPayResponse.buildSuccess(obj));
    }

    /**
     * 根据type查询配置信息
     * @return
     */
    @RequestMapping("/get")
    @ResponseBody
    public ResponseEntity<?> get(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        String type = getStringRequired(param, "type");
        JSONObject obj = commonService.sysConfigService.getSysConfigObj(type);
        return ResponseEntity.ok(XxPayResponse.buildSuccess(obj));
    }

    /**
     * 修改配置信息
     * @return
     */
    @RequestMapping("/update")
    @ResponseBody
    @MethodLog( remark = "修改配置信息" )
    public ResponseEntity<?> update(HttpServletRequest request) {

        JSONObject param = getJsonParam(request);  //所有请求参数
        String type = param.getString("type");  //类型

        Map<String, String> updateMap = new HashMap<>();  //更新的集合

        if("sett".equals(type)) { // [sett] 结算设置

            // 将金额元转成分
            handleParamAmount(param, "drawMaxDayAmount", "maxDrawAmount", "minDrawAmount", "feeLevel", "drawFeeLimit");

            //将json对象转换为 map格式， 剔除无关数据
            updateMap = convertMap(param, "drawFlag", "allowDrawWeekDay", "drawDayStartTime", "drawDayEndTime", "dayDrawTimes",
                    "drawMaxDayAmount", "maxDrawAmount", "minDrawAmount", "feeType", "feeRate", "feeLevel", "drawFeeLimit", "settType", "settMode");
            if (StringUtils.isBlank(updateMap.get("drawDayStartTime")) || StringUtils.isBlank(updateMap.get("drawDayEndTime"))) {
                return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_SERVICE_DRAW_TIME_NOTBLANK));
            }
        }else if ("safe".equals(type)) {  //[safe] 安全设置

            String mchDefaultPwd = param.getString("mchDefaultPwd");
            String mchDefaultPayPwd = param.getString("mchDefaultPayPwd");
            String mgrSuperPwd = param.getString("mgrSuperPwd");
            // 如果登录密码不为空,则修改登录密码
            if (StringUtils.isNotBlank(mchDefaultPwd)) {
                BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
                if (!StrUtil.checkPassword(mchDefaultPwd)) {  // 判断新登录密码格式
                    return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MCH_PASSWORD_FORMAT_FAIL));
                }
                updateMap.put("mchDefaultPwd", encoder.encode(mchDefaultPwd));
            }
            // 如果支付密码不为空,则修改支付密码
            if (StringUtils.isNotBlank(mchDefaultPayPwd)) {
                if (!StrUtil.checkPassword(mchDefaultPayPwd)) { // 判断新支付密码格式
                    return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MCH_PASSWORD_FORMAT_FAIL));
                }
                updateMap.put("mchDefaultPayPwd", MD5Util.string2MD5(mchDefaultPayPwd));
            }
            // 是否为超级管理员，如果为超级管理员判断超级密码是否为空，不为空则修改超级密码
            if (StringUtils.isNotBlank(mgrSuperPwd)) {
                if (getUser().getIsSuperAdmin() != MchConstant.PUB_YES){
                    return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MGR_SUPER_PASSWORD_UPDATE_LIMIT));
                }
                if (!StrUtil.checkPassword(mgrSuperPwd)) { // 判断新密码格式
                    return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MCH_PASSWORD_FORMAT_FAIL));
                }
                updateMap.put("mgrSuperPwd", MD5Util.string2MD5(mgrSuperPwd));
            }
        }else if("site".equals(type)){ //[site] 网站设置

            if(StringUtils.isEmpty(param.getString("siteTitle"))){
                return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_PARAM_ERROR));
            }
            updateMap.put("siteTitle", param.getString("siteTitle"));
            updateMap.put("statisticalCode", param.getString("statisticalCode"));
            updateMap.put("copyRight", param.getString("copyRight"));
            updateMap.put("serviceTel", param.getString("serviceTel"));
            updateMap.put("serviceQQ", param.getString("serviceQQ"));
            updateMap.put("siteLogo", param.getString("siteLogo"));
            updateMap.put("mchHomeBanner", param.getString("mchHomeBanner"));
            updateMap.put("siteIcon", param.getString("siteIcon"));
            updateMap.put("mainAdvert", param.getString("mainAdvert"));
            updateMap.put("mainAdvertEn", param.getString("mainAdvertEn"));
            updateMap.put("subAdvert", param.getString("subAdvert"));
        }else if("agentpay".equals(type)){ //[agentpay] 代付设置

            Byte agpayOutAccount = param.getByte(MchConstant.AGENTPAY_OUT_ACCOUNT_CONFIG_KEY);
            Byte agentpayAuditType = param.getByte("agentpayAuditType");
            Byte agentpayCheckRepeatFlag = param.getByte("agentpayCheckRepeatFlag");
            Integer agentpayCheckRepeatTime = param.getInteger("agentpayCheckRepeatTime");
            Byte agentpaySnatchFlag = param.getByte("agentpaySnatchFlag");
            if( agpayOutAccount == null || agentpayAuditType == null ||
              (MchConstant.AGENTPAY_OUT_ACCOUNT_BALANCE != agpayOutAccount && MchConstant.AGENTPAY_OUT_ACCOUNT_AGBALANCE != agpayOutAccount) ){
                return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_PARAM_ERROR));
            }
            updateMap.put(MchConstant.AGENTPAY_OUT_ACCOUNT_CONFIG_KEY, agpayOutAccount + "");
            updateMap.put("agentpayAuditType", agentpayAuditType + "");
            updateMap.put("agentpayCheckRepeatFlag", agentpayCheckRepeatFlag + "");
            updateMap.put("agentpayCheckRepeatTime", agentpayCheckRepeatTime + "");
            updateMap.put("agentpaySnatchFlag", agentpaySnatchFlag + "");

            updateMap.put("agentpayMchConfigFlag", param.getInteger("agentpayMchConfigFlag") + "");
            updateMap.put("agentpayMchConfig2QueryOrderTime", param.getInteger("agentpayMchConfig2QueryOrderTime") + "");
            updateMap.put("agentpayChoosePayType", param.getString("agentpayChoosePayType"));

        }else if("doc".equals(type)){ //[doc] 接口文档设置
            updateMap.put("payApiDoc", param.getString("payApiDoc"));
            updateMap.put("agentpayApiDoc", param.getString("agentpayApiDoc"));
        }else if("applicationConfig".equals(type)){ //["applicationConfig"] 系统参数配置

            updateMap.put("mgrSiteUrl", param.getString("mgrSiteUrl"));
            updateMap.put("mchSiteUrl", param.getString("mchSiteUrl"));
            updateMap.put("agentSiteUrl", param.getString("agentSiteUrl"));
            updateMap.put("paySiteUrl", param.getString("paySiteUrl"));
            updateMap.put("wxOauth2CodeUrl", param.getString("wxOauth2CodeUrl"));
            updateMap.put("taskReissuePaySwitch", param.getString("taskReissuePaySwitch"));
            updateMap.put("taskReissuePayIp", param.getString("taskReissuePayIp"));
            updateMap.put("taskReissueTransSwitch", param.getString("taskReissueTransSwitch"));
            updateMap.put("taskReissueTransIp", param.getString("taskReissueTransIp"));
            updateMap.put("cleanFlag", param.getString("cleanFlag"));

        }else if ("amountFloat".equals(type)) {
            String amountFloatConfig = param.getString("amountFloatConfig");
            updateMap.put("amountFloatConfig", amountFloatConfig);
        }else if ("uploadFile".equals(type)) { //上传附件设置
            updateMap.put("uploadFileSaveType", param.getString("uploadFileSaveType"));
            updateMap.put("ossEndpoint", param.getString("ossEndpoint"));
            updateMap.put("ossBucketName", param.getString("ossBucketName"));
            updateMap.put("ossAccessKeyId", param.getString("ossAccessKeyId"));
            updateMap.put("ossAccessKeySecret", param.getString("ossAccessKeySecret"));
        }else if ("smsConfig".equals(type)) { //短信设置
            updateMap.put("smsConfig", param.getString("smsConfig"));
        }else if ("loginSafeConfig".equals(type)) {
            String btSignConfig = param.getString("btSignConfig");
            String btUrlConfig = param.getString("btUrlConfig");
            String loginCountConfig = param.getString("loginCountConfig");
            String loginToBlackType = param.getString("loginToBlackType");
            updateMap.put("btSignConfig", btSignConfig);
            updateMap.put("btUrlConfig", btUrlConfig);
            updateMap.put("loginCountConfig", loginCountConfig);
            updateMap.put("loginToBlackType", loginToBlackType);
            if ("1".equals(loginToBlackType)) {
                // 检测宝塔配置
                Boolean result = BtUtil.testBtConfig(btSignConfig, btUrlConfig);
                if (!result) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_BT_SIGIN_OR_URL_ERROR));
            }
        }else if ("sysTips".equals(type)) {

            updateMap.put("mgrPayOrderAllTipFlag", param.getString("mgrPayOrderAllTipFlag"));
            updateMap.put("mgrPayOrderSoundFlag", param.getString("mgrPayOrderSoundFlag"));
            updateMap.put("mgrAgentpayOrderAllTipFlag", param.getString("mgrAgentpayOrderAllTipFlag"));
            updateMap.put("mgrAgentpayOrderSoundFlag", param.getString("mgrAgentpayOrderSoundFlag"));
            updateMap.put("mgrSettOrderAllTipFlag", param.getString("mgrSettOrderAllTipFlag"));
            updateMap.put("mgrSettOrderSoundFlag", param.getString("mgrSettOrderSoundFlag"));

        }else{ //未匹配到任何类型
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_PARAM_ERROR));
        }
        int updateRow = commonService.sysConfigService.update(updateMap);
        if(updateRow <= 0) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));

        if("applicationConfig".equals(type)){ //["applicationConfig"] 系统参数配置

          //发送订阅消息： 推送到所有节点进行更新
          mqTopic4ModifySysConfig.push("applicationConfig");
        }else if("site".equals(type)){ //["site"] 系统参数配置

            //发送订阅消息： 推送到所有节点进行更新
            mqTopic4ModifySysConfig.push("site");
        }else if("uploadFile".equals(type)){ //["uploadFile"] 系统参数配置

            //发送订阅消息： 推送到所有节点进行更新
            mqTopic4ModifySysConfig.push("uploadFile");
        }else if("smsConfig".equals(type)){ //["smsConfig"] 系统参数配置

            //发送订阅消息： 推送到所有节点进行更新
            mqTopic4ModifySysConfig.push("smsConfig");
        }else if("agentpay".equals(type)){
            //发送订阅消息： 推送到所有节点进行更新
            mqTopic4ModifySysConfig.push("agentpayConfig");
        }else if("sysTips".equals(type)){

            //发送订阅消息： 推送到所有节点进行更新
            mqTopic4ModifySysConfig.push("sysTipsConfig");

        }

        return ResponseEntity.ok(BizResponse.buildSuccess());
    }

    /**
     * 清理数据
     * @return
     */
    @RequestMapping("/clean")
    @ResponseBody
    public ResponseEntity<?> clean(HttpServletRequest request) {
        //验证删除开关是否打开
        DBApplicationConfig config = getDBApplicationConfig();
        if (config.getCleanFlag() != MchConstant.PUB_YES) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MGR_DATA_CLEAN_FLAG_OFF));
        }
        JSONObject param = getJsonParam(request);
        String password = getStringRequired(param, "pass");
        String customTime = getString(param, "customTime");
        String createTimeStr = getString(param, "cleanTime");
        String cleanTableCheck = getStringRequired(param, "cleanTableCheck");
        // 判断输入的超级密码是否正确
        if(!checkMgrSuperPwd(password)) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MGR_SUPER_PASSWORD_NOT_MATCH));
        }
        //判断若为自定义时间  时间范围必填
        if ("2".equals(customTime)) {
            if (StringUtils.isBlank(createTimeStr)) throw new RuntimeException("请选择时间范围");
        }
        String[] cleanCheck = cleanTableCheck.split(",");
        if (StringUtils.isBlank(cleanCheck[0])) throw new RuntimeException("请选择要清理的表");
        List<String> list = Arrays.asList(cleanCheck);
        int count = commonService.sysConfigService.cleanData(list, createTimeStr);
        return ResponseEntity.ok(XxPayResponse.buildSuccess(count));
    }

    /**
     * 根据key 将 jsonObject 转换为 map格式。
     * @param jsonObject
     * @param keys
     * @return
     */
    private Map<String, String> convertMap(JSONObject jsonObject, String ... keys){

        Map<String, String> result = new HashMap<>();
        Arrays.asList(keys).stream().forEach(key -> result.put(key, jsonObject.getString(key)));
        return result;

    }

}